package com.example.pt.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.pt.entity.TorrentClickHistory;
import com.example.pt.entity.TorrentFile;
import com.example.pt.mapper.TorrentClickHistoryMapper;
import com.example.pt.repository.TorrentFileRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class RecommendationService {
    
    private static final Logger logger = LoggerFactory.getLogger(RecommendationService.class);

    @Autowired
    private TorrentClickHistoryMapper torrentClickHistoryMapper;

    @Autowired
    private TorrentFileRepository torrentFileRepository;
    
    @Autowired
    private RecommendationScoreService recommendationScoreService;
    
    @Autowired
    private RecommendationFeedbackService recommendationFeedbackService;

    @Autowired
    private PromotionService promotionService;

    private static final int DEFAULT_RECOMMENDATION_COUNT = 10;
    private static final int DEFAULT_HISTORY_DAYS = 30;
    
    // 批次ID生成器，用于前端标识同一批次的推荐内容
    private String generateBatchId() {
        return UUID.randomUUID().toString().replace("-", "").substring(0, 16);
    }

    /**
     * 记录用户点击种子行为
     * @param uid 用户ID
     * @param tid 种子ID
     */
    public void recordUserClick(Integer uid, Integer tid) {
        try {
            logger.info("开始记录用户点击行为: uid={}, tid={}", uid, tid);
            System.out.println("开始记录用户点击行为: uid=" + uid + ", tid=" + tid);
            
            // 检查用户ID是否有效
            if (uid == null || uid <= 0) {
                logger.warn("无效的用户ID: {}, 不记录点击行为", uid);
                System.out.println("无效的用户ID: " + uid + ", 不记录点击行为");
                return;
            }
            
            // 检查用户和种子是否存在
            try {
                int userExists = torrentClickHistoryMapper.checkUserExists(uid);
                System.out.println("检查用户是否存在: uid=" + uid + ", 结果=" + userExists);
                
                int torrentExists = torrentClickHistoryMapper.checkTorrentExists(tid);
                System.out.println("检查种子是否存在: tid=" + tid + ", 结果=" + torrentExists);
                
                if (userExists == 0) {
                    logger.warn("用户ID {} 在数据库中不存在，不记录点击行为", uid);
                    System.out.println("用户ID " + uid + " 在数据库中不存在，不记录点击行为");
                    return;
                }
                
                if (torrentExists == 0) {
                    logger.warn("种子ID {} 在数据库中不存在，不记录点击行为", tid);
                    System.out.println("种子ID " + tid + " 在数据库中不存在，不记录点击行为");
                    return;
                }
                
                logger.info("用户和种子验证通过: 用户ID={} (存在={})，种子ID={} (存在={})", 
                        uid, userExists > 0, tid, torrentExists > 0);
                System.out.println("用户和种子验证通过: 用户ID=" + uid + " (存在=" + (userExists > 0) + 
                        ")，种子ID=" + tid + " (存在=" + (torrentExists > 0) + ")");
            } catch (Exception e) {
                logger.error("检查用户和种子存在性时发生错误: {}", e.getMessage(), e);
                System.out.println("检查用户和种子存在性时发生错误: " + e.getMessage());
                e.printStackTrace();
            }
            
            // 检查种子是否存在（获取详细信息）
            Optional<TorrentFile> torrentOpt = torrentFileRepository.findByTid(tid);
            if (!torrentOpt.isPresent()) {
                logger.warn("尝试记录不存在的种子点击: uid={}, tid={}", uid, tid);
                System.out.println("尝试记录不存在的种子点击: uid=" + uid + ", tid=" + tid);
                return;
            }
            
            TorrentFile torrent = torrentOpt.get();
            logger.debug("找到种子信息: tid={}, 标题={}, 类别={}", tid, torrent.getTitle(), torrent.getCategory());
            System.out.println("找到种子信息: tid=" + tid + ", 标题=" + torrent.getTitle() + ", 类别=" + torrent.getCategory());
            
            // 尝试两种方式插入记录
            try {
                // 1. 首先尝试使用忽略外键约束的方式插入
                Date clickTime = new Date();
                System.out.println("尝试使用忽略外键约束的方式插入记录: uid=" + uid + ", tid=" + tid + ", 时间=" + clickTime);
                int ignoreResult = torrentClickHistoryMapper.insertIgnoreFK(uid, tid, clickTime);
                System.out.println("忽略外键约束插入结果: " + ignoreResult);
                
                if (ignoreResult > 0) {
                    logger.info("成功记录用户点击(忽略外键方式): uid={}, tid={}, 种子标题={}, 类别={}", 
                            uid, tid, torrent.getTitle(), torrent.getCategory());
                    System.out.println("成功记录用户点击(忽略外键方式): uid=" + uid + ", tid=" + tid);
                    return;
                } else {
                    logger.warn("使用忽略外键方式插入失败，尝试标准方式");
                    System.out.println("使用忽略外键方式插入失败，尝试标准方式");
                }
                
                // 2. 如果忽略外键方式失败，尝试标准方式
                TorrentClickHistory clickHistory = new TorrentClickHistory();
                clickHistory.setUid(uid);
                clickHistory.setTid(tid);
                clickHistory.setClickTime(clickTime);
                
                logger.debug("准备插入点击历史记录: {}", clickHistory);
                System.out.println("准备插入点击历史记录: uid=" + clickHistory.getUid() + 
                        ", tid=" + clickHistory.getTid() + ", 时间=" + clickHistory.getClickTime());
                
                int result = torrentClickHistoryMapper.insert(clickHistory);
                System.out.println("标准方式插入结果: " + result);
                
                if (result > 0) {
                    logger.info("成功记录用户点击(标准方式): uid={}, tid={}, 种子标题={}, 类别={}", 
                            uid, tid, torrent.getTitle(), torrent.getCategory());
                    System.out.println("成功记录用户点击(标准方式): uid=" + uid + ", tid=" + tid);
                } else {
                    logger.warn("记录用户点击失败: uid={}, tid={}, 数据库插入返回={}", uid, tid, result);
                    System.out.println("记录用户点击失败: uid=" + uid + ", tid=" + tid + ", 数据库插入返回=" + result);
                }
            } catch (Exception e) {
                logger.error("插入点击历史记录失败: {}", e.getMessage(), e);
                System.out.println("插入点击历史记录失败: " + e.getMessage());
                e.printStackTrace();
                logger.info("请检查数据库约束和表结构是否正确");
                System.out.println("请检查数据库约束和表结构是否正确");
            }
        } catch (Exception e) {
            logger.error("记录用户点击失败: uid={}, tid={}, 错误={}", uid, tid, e.getMessage(), e);
            System.out.println("记录用户点击失败: uid=" + uid + ", tid=" + tid + ", 错误=" + e.getMessage());
            e.printStackTrace();
            // 记录错误但不中断用户体验
        }
    }

    /**
     * 获取推荐种子列表（按照分数由高到低返回所有推荐种子，不分页）
     * @param uid 用户ID
     * @return 推荐种子列表
     */
    public List<TorrentFile> getRecommendedTorrents(Integer uid) {
        try {
            long startTime = System.currentTimeMillis();
            
            logger.info("开始为用户 {} 生成推荐种子（不分页，返回全部）", uid);
            
            // 获取用户点击历史统计信息
            Map<String, Object> userStats = recommendationScoreService.getUserClickHistoryStats(uid);
            List<TorrentClickHistory> userHistory = (List<TorrentClickHistory>) userStats.get("userClickHistory");
            
            // 获取用户点击过的种子ID列表
            @SuppressWarnings("unchecked")
            List<Integer> userClickedTids = (List<Integer>) userStats.get("clickedTids");
            
            // 获取用户不感兴趣的种子ID列表
            List<Integer> userDislikedTids = recommendationFeedbackService.getUserDislikedTorrentIds(uid);
            
            // 合并用户已点击和不感兴趣的种子ID列表，这些都不应该再推荐
            Set<Integer> excludeTids = new HashSet<>(userClickedTids);
            excludeTids.addAll(userDislikedTids);
            
            // 如果用户没有点击历史，则返回热门种子（但排除不感兴趣的）
            if (userHistory == null || userHistory.isEmpty()) {
                logger.info("用户 {} 没有点击历史，返回热门种子（排除不感兴趣的）", uid);
                
                // 获取热门种子，排除不感兴趣的种子
                List<TorrentFile> allHotTorrents = getHotTorrents(Integer.MAX_VALUE, new HashSet<>(userDislikedTids));
                
                long endTime = System.currentTimeMillis();
                logger.info("为用户 {} 生成热门推荐完成，共 {} 个种子，耗时 {} ms", 
                        uid, allHotTorrents.size(), (endTime - startTime));
                
                return allHotTorrents;
            }
            
            // 获取用户类别点击统计
            @SuppressWarnings("unchecked")
            Map<Integer, Integer> categoryClickCounts = (Map<Integer, Integer>) userStats.get("categoryClickCounts");
            
            // 获取用户类别不感兴趣统计
            Map<Integer, Integer> categoryDislikeCounts = recommendationFeedbackService.getUserCategoryDislikeStats(uid);
            
            // 获取用户总点击数
            int totalUserClicks = (int) userStats.get("totalUserClicks");
            
            // 获取最高浏览量
            int maxViewCount = recommendationScoreService.getMaxViewCount();
            logger.debug("系统最高浏览量: {}", maxViewCount);
            
            // 获取所有可推荐的种子（状态正常且用户未点击过且未标记不感兴趣）
            List<TorrentFile> candidateTorrents = torrentFileRepository.findAll().stream()
                    .filter(t -> t.getStatus() == 1 && !excludeTids.contains(t.getTid()))
                    .collect(Collectors.toList());
            
            logger.debug("获取到 {} 个候选种子进行推荐", candidateTorrents.size());
            
            // 如果没有可推荐的种子，返回热门种子
            if (candidateTorrents.isEmpty()) {
                logger.warn("没有可推荐的种子，用户 {} 可能已点击或不感兴趣所有种子，返回热门种子", uid);
                return getHotTorrents(Integer.MAX_VALUE, new HashSet<>(userDislikedTids));
            }
            
            // 计算每个种子的推荐分数
            Map<TorrentFile, Double> torrentScores = new HashMap<>();
            
            for (TorrentFile torrent : candidateTorrents) {
                double score = recommendationScoreService.calculateRecommendationScore(
                        uid, torrent, userHistory, categoryClickCounts, totalUserClicks, maxViewCount);
                
                // 如果用户对该种子的类别有负反馈，降低其推荐分数
                Integer dislikeCount = categoryDislikeCounts.get(torrent.getCategory());
                if (dislikeCount != null && dislikeCount > 0) {
                    // 每有一个负反馈，分数降低10%，最多降低50%
                    double penalty = Math.min(0.5, dislikeCount * 0.1);
                    score *= (1 - penalty);
                    logger.debug("种子 {} 类别 {} 有 {} 个负反馈，分数降低 {}%", 
                        torrent.getTid(), torrent.getCategory(), dislikeCount, penalty * 100);
                }
                
                torrentScores.put(torrent, score);
            }
            
            // 按推荐分数降序排列
            List<TorrentFile> allRecommendedTorrents = torrentScores.entrySet().stream()
                    .sorted(Map.Entry.<TorrentFile, Double>comparingByValue().reversed())
                    .map(Map.Entry::getKey)
                    .collect(Collectors.toList());
            
            logger.debug("基于分数排序后得到 {} 个推荐种子", allRecommendedTorrents.size());
            
            // 如果推荐数量不足，则补充热门种子
            if (allRecommendedTorrents.isEmpty()) {
                logger.debug("推荐数量为0，需要补充热门种子");
                
                List<TorrentFile> hotTorrents = getHotTorrents(Integer.MAX_VALUE, new HashSet<>(userDislikedTids)).stream()
                        .filter(t -> !excludeTids.contains(t.getTid()))
                        .collect(Collectors.toList());
                
                allRecommendedTorrents.addAll(hotTorrents);
                logger.debug("补充后共有 {} 个推荐种子", allRecommendedTorrents.size());
            }
            
            // 确保所有推荐的种子都是状态为1的
            List<TorrentFile> finalRecommendations = allRecommendedTorrents.stream()
                    .filter(t -> t.getStatus() == 1)
                    .collect(Collectors.toList());
            
            if (finalRecommendations.size() < allRecommendedTorrents.size()) {
                logger.warn("过滤掉了 {} 个非状态为1的种子", allRecommendedTorrents.size() - finalRecommendations.size());
            }
            
            // 记录推荐结果的类别分布
            if (logger.isDebugEnabled() && !finalRecommendations.isEmpty()) {
                Map<Integer, Integer> categoryDistribution = new HashMap<>();
                for (TorrentFile torrent : finalRecommendations) {
                    int category = torrent.getCategory();
                    categoryDistribution.put(category, categoryDistribution.getOrDefault(category, 0) + 1);
                }
                
                logger.debug("推荐种子类别分布: {}", categoryDistribution);
            }
            
            long endTime = System.currentTimeMillis();
            logger.info("为用户 {} 生成个性化推荐完成，共 {} 个种子，耗时 {} ms", 
                    uid, finalRecommendations.size(), (endTime - startTime));
            
            return finalRecommendations;
        } catch (Exception e) {
            logger.error("生成推荐种子时发生错误: {}", e.getMessage(), e);
            return List.of();
        }
    }

    /**
     * 保留原始分页方法以兼容旧代码
     */
    public List<TorrentFile> getRecommendedTorrents(Integer uid, Integer pageSize, Integer pageNum) {
        // 直接调用不分页版本，然后手动分页
        List<TorrentFile> allTorrents = getRecommendedTorrents(uid);
        return applyPagination(allTorrents, pageNum, pageSize);
    }

    /**
     * 获取推荐种子列表，并附带批次ID（不分页版本）
     * @param uid 用户ID
     * @return 包含推荐种子列表和批次ID的Map
     */
    public Map<String, Object> getRecommendedTorrentsWithBatchId(Integer uid) {
        Map<String, Object> result = new HashMap<>();
        
        // 生成批次ID
        String batchId = generateBatchId();
        result.put("batchId", batchId);
        
        // 获取所有推荐种子
        List<TorrentFile> torrents = getRecommendedTorrents(uid);
        
        // 确保种子列表不为null
        if (torrents == null) {
            torrents = new ArrayList<>();
            logger.warn("推荐种子列表为null，已替换为空列表");
        }
        
        // 将种子列表转换为Map列表，并将category从int转换为字符串名称
        List<Map<String, Object>> torrentMapList = torrents.stream().map(torrent -> {
            Map<String, Object> torrentMap = new HashMap<>();
            Map promotion = promotionService.getMaxDiscountInfo(torrent.getTid());
            torrentMap.put("tid", torrent.getTid());
            torrentMap.put("uid", torrent.getUid());
            torrentMap.put("title", torrent.getTitle());
            torrentMap.put("fileUrl", torrent.getFileUrl());
            torrentMap.put("category", com.example.pt.enums.Category.getNameByValue(torrent.getCategory()));
            torrentMap.put("format", torrent.getFormat());
            torrentMap.put("language", torrent.getLanguage());
            torrentMap.put("description", torrent.getDescription());
            torrentMap.put("fileSize", torrent.getFileSize());
            torrentMap.put("uploadTime", torrent.getUploadTime());
            torrentMap.put("status", torrent.getStatus());
            torrentMap.put("downloadCount", torrent.getDownloadCount());
            torrentMap.put("viewCount", torrent.getViewCount());
            torrentMap.put("seederCount", torrent.getSeederCount());
            torrentMap.put("promotionName",promotion.get("discountName"));
            torrentMap.put("promotionStart",promotion.get("startTime"));
            torrentMap.put("promotionEnd",promotion.get("endTime"));
            return torrentMap;
        }).collect(Collectors.toList());
        
        result.put("torrents", torrentMapList);
        
        // 获取数据库中所有符合推荐条件的种子总数
        int totalRecommendableTorrents = getTotalRecommendableTorrentsCount(uid);
        result.put("total", totalRecommendableTorrents);
        
        return result;
    }

    /**
     * 保留原始分页方法以兼容旧代码
     */
    public Map<String, Object> getRecommendedTorrentsWithBatchId(Integer uid, Integer pageSize, Integer pageNum) {
        Map<String, Object> result = getRecommendedTorrentsWithBatchId(uid);
        
        // 添加分页信息
        if (pageSize == null || pageSize <= 0) {
            pageSize = DEFAULT_RECOMMENDATION_COUNT;
        }
        
        if (pageNum == null || pageNum < 1) {
            pageNum = 1;
        }
        
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> allTorrents = (List<Map<String, Object>>) result.get("torrents");
        
        // 手动分页
        int startIndex = (pageNum - 1) * pageSize;
        if (startIndex >= allTorrents.size()) {
            startIndex = 0;
            pageNum = 1;
        }
        int endIndex = Math.min(startIndex + pageSize, allTorrents.size());
        
        List<Map<String, Object>> pagedTorrents = (startIndex < endIndex) ?
            allTorrents.subList(startIndex, endIndex) : new ArrayList<>();
        
        // 更新结果
        result.put("torrents", pagedTorrents);
        
        // 添加分页信息
        int totalPages = (int) Math.ceil((double) allTorrents.size() / pageSize);
        result.put("totalPages", totalPages);
        result.put("currentPage", pageNum);
        result.put("pageSize", pageSize);
        
        return result;
    }

    /**
     * 获取数据库中所有符合推荐条件的种子总数
     * @param uid 用户ID
     * @return 符合推荐条件的种子总数
     */
    private int getTotalRecommendableTorrentsCount(Integer uid) {
        try {
            // 获取用户点击历史统计信息
            Map<String, Object> userStats = recommendationScoreService.getUserClickHistoryStats(uid);
            
            // 获取用户点击过的种子ID列表
            @SuppressWarnings("unchecked")
            List<Integer> userClickedTids = (List<Integer>) userStats.get("clickedTids");
            
            // 获取用户不感兴趣的种子ID列表
            List<Integer> userDislikedTids = recommendationFeedbackService.getUserDislikedTorrentIds(uid);
            
            // 合并用户已点击和不感兴趣的种子ID列表，这些都不应该再推荐
            Set<Integer> excludeTids = new HashSet<>(userClickedTids);
            excludeTids.addAll(userDislikedTids);
            
            // 获取所有可推荐的种子（状态正常且用户未点击过且未标记不感兴趣）
            long recommendableTorrentsCount = torrentFileRepository.findAll().stream()
                    .filter(t -> t.getStatus() == 1 && !excludeTids.contains(t.getTid()))
                    .count();
            
            logger.debug("用户 {} 可推荐种子总数: {}，已排除 {} 个已点击或不感兴趣的种子", 
                    uid, recommendableTorrentsCount, excludeTids.size());
            
            return (int) recommendableTorrentsCount;
        } catch (Exception e) {
            logger.error("获取可推荐种子总数时发生错误: {}", e.getMessage(), e);
            return 0;
        }
    }

    /**
     * 获取热门种子列表
     * @param count 推荐数量
     * @param excludeTids 需要排除的种子ID列表，可以为null
     * @return 热门种子列表
     */
    public List<TorrentFile> getHotTorrents(int count, Set<Integer> excludeTids) {
        try {
            // 计算30天前的日期
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DAY_OF_MONTH, -DEFAULT_HISTORY_DAYS);
            Date startTime = calendar.getTime();
            Date endTime = new Date();
            
            logger.debug("获取 {} 天内的热门种子，请求数量: {}, 排除 {} 个种子", 
                    DEFAULT_HISTORY_DAYS, count, excludeTids != null ? excludeTids.size() : 0);
            
            // 获取一段时间内的热门种子ID及点击次数
            List<Map<String, Object>> hotTorrentMaps = torrentClickHistoryMapper.findHotTorrentsInPeriod(
                    startTime, endTime, count * 2); // 请求更多种子以应对过滤
            
            // 获取热门种子ID列表，并过滤掉需要排除的ID
            List<Integer> hotTorrentIds = hotTorrentMaps.stream()
                    .map(map -> ((Number) map.get("tid")).intValue())
                    .filter(tid -> excludeTids == null || !excludeTids.contains(tid))
                    .collect(Collectors.toList());
            
            logger.debug("基于点击历史找到 {} 个热门种子ID（已排除不感兴趣的）", hotTorrentIds.size());
            
            // 如果没有足够的热门种子记录，则获取浏览量最高的种子（同样排除不感兴趣的）
            if (hotTorrentIds.size() < count) {
                logger.debug("点击历史不足，基于viewCount补充热门种子");
                
                List<TorrentFile> allTorrents = torrentFileRepository.findAll().stream()
                        .filter(t -> t.getStatus() == 1) // 只推荐状态正常的种子
                        .filter(t -> excludeTids == null || !excludeTids.contains(t.getTid())) // 排除不感兴趣的种子
                        .sorted(Comparator.comparing(TorrentFile::getViewCount).reversed())
                        .limit(count)
                        .collect(Collectors.toList());
                
                return allTorrents;
            }
            
            // 获取热门种子详细信息，并按原来的排序返回
            List<TorrentFile> result = new ArrayList<>();
            for (Integer tid : hotTorrentIds) {
                Optional<TorrentFile> torrentOpt = torrentFileRepository.findByTid(tid);
                if (torrentOpt.isPresent() && torrentOpt.get().getStatus() == 1) {
                    result.add(torrentOpt.get());
                }
            }
            
            logger.debug("成功获取 {} 个热门种子的详细信息", result.size());
            
            // 如果结果数量不足，则添加浏览量最高的种子（排除不感兴趣的）
            if (result.size() < count) {
                List<Integer> existingIds = result.stream()
                        .map(TorrentFile::getTid)
                        .collect(Collectors.toList());
                
                // 合并已有结果和排除列表
                Set<Integer> combinedExcludeIds = new HashSet<>(existingIds);
                if (excludeTids != null) {
                    combinedExcludeIds.addAll(excludeTids);
                }
                
                logger.debug("热门种子数量不足，基于viewCount补充 {} 个种子", count - result.size());
                
                List<TorrentFile> additionalTorrents = torrentFileRepository.findAll().stream()
                        .filter(t -> t.getStatus() == 1 && !combinedExcludeIds.contains(t.getTid()))
                        .sorted(Comparator.comparing(TorrentFile::getViewCount).reversed())
                        .limit(count - result.size())
                        .collect(Collectors.toList());
                
                result.addAll(additionalTorrents);
            }
            
            // 记录热门种子的类别分布
            if (logger.isDebugEnabled()) {
                Map<Integer, Integer> categoryDistribution = new HashMap<>();
                for (TorrentFile torrent : result) {
                    int category = torrent.getCategory();
                    categoryDistribution.put(category, categoryDistribution.getOrDefault(category, 0) + 1);
                }
                
                logger.debug("热门种子类别分布: {}", categoryDistribution);
            }
            
            logger.info("获取热门种子完成，共 {} 个种子", result.size());
            
            return result;
        } catch (Exception e) {
            logger.error("获取热门种子时发生错误: {}", e.getMessage(), e);
            return List.of();
        }
    }

    /**
     * 获取热门种子列表（不排除任何种子）
     * @param count 推荐数量
     * @return 热门种子列表
     */
    public List<TorrentFile> getHotTorrents(int count) {
        return getHotTorrents(count, null);
    }

    /**
     * 获取热门种子列表，并附带批次ID
     * @param count 推荐数量
     * @return 包含热门种子列表和批次ID的Map
     */
    public Map<String, Object> getHotTorrentsWithBatchId(int count) {
        Map<String, Object> result = new HashMap<>();
        
        // 生成批次ID
        String batchId = generateBatchId();
        result.put("batchId", batchId);
        
        // 获取热门种子
        List<TorrentFile> torrents = getHotTorrents(count);
        
        // 确保种子列表不为null
        if (torrents == null) {
            torrents = new ArrayList<>();
            logger.warn("热门种子列表为null，已替换为空列表");
        }
        
        // 将种子列表转换为Map列表，并将category从int转换为字符串名称
        List<Map<String, Object>> torrentMapList = torrents.stream().map(torrent -> {
            Map<String, Object> torrentMap = new HashMap<>();
            Map<String, Object> promotion = promotionService.getMaxDiscountInfo(torrent.getTid());
            torrentMap.put("tid", torrent.getTid());
            torrentMap.put("uid", torrent.getUid());
            torrentMap.put("title", torrent.getTitle());
            torrentMap.put("fileUrl", torrent.getFileUrl());
            torrentMap.put("category", com.example.pt.enums.Category.getNameByValue(torrent.getCategory()));
            torrentMap.put("format", torrent.getFormat());
            torrentMap.put("language", torrent.getLanguage());
            torrentMap.put("description", torrent.getDescription());
            torrentMap.put("fileSize", torrent.getFileSize());
            torrentMap.put("uploadTime", torrent.getUploadTime());
            torrentMap.put("status", torrent.getStatus());
            torrentMap.put("downloadCount", torrent.getDownloadCount());
            torrentMap.put("viewCount", torrent.getViewCount());
            torrentMap.put("seederCount", torrent.getSeederCount());
            torrentMap.put("promotionName", promotion.get("discountName"));
            torrentMap.put("promotionStart", promotion.get("startTime"));
            torrentMap.put("promotionEnd", promotion.get("endTime"));
            return torrentMap;
        }).collect(Collectors.toList());
        
        result.put("torrents", torrentMapList);
        
        return result;
    }

    /**
     * 将分页逻辑应用到列表
     * @param list 原始列表
     * @param pageNum 页码（从1开始）
     * @param pageSize 每页大小
     * @return 分页后的列表
     */
    private <T> List<T> applyPagination(List<T> list, int pageNum, int pageSize) {
        if (list == null || list.isEmpty()) {
            return List.of();
        }
        
        // 确保页码至少为1
        int page = Math.max(1, pageNum);
        
        // 计算起始索引，页码从1开始，所以需要减1
        int startIndex = (page - 1) * pageSize;
        
        // 如果起始索引超出列表范围，返回空列表
        if (startIndex >= list.size()) {
            return List.of();
        }
        
        int endIndex = Math.min(startIndex + pageSize, list.size());
        
        return list.subList(startIndex, endIndex);
    }
} 